
/*
    用于保证异步下的执行顺序
    process(["p1", "p2"], () => {
        console.log("p3 ready");
    }, "p3")
    process(() => {
        console.log("p1 ready");
    }, "p1")
    process(() => {
        console.log("p2 ready");
    }, "p2")

*/
var name_count = 0; // 如果未提供名称，则指定一个默认名称供调用，但是执行完后不会放入finished，相当于匿名注册
var map = {
    finished: {}, // 已完成
    emited: {},
    awaiting: {} // 等待执行
};

function Unit(premise /*执行前提*/, fn/*执行函数*/, name/*注册名称*/) {
    if(typeof(premise) == "function") { // 代表没有执行前提
        this.premise = [];
        this.fn = premise;
        this.name = fn || "_" + name_count++;
    }else {
        this.premise = typeof(premise) == "string" ? [premise] : premise;
        this.fn = fn;
        this.name = name || "_" + name_count++;
    }
    this._premise_begin_index = 0;
}

function process(premise /*执行前提*/, fn/*执行函数*/, name/*注册名称*/) {
    var unit = new Unit(premise, fn, name);
    var b = false;
    if(map.awaiting[unit.name]) {
        delete map.awaiting[unit.name];
        b = true;
    }else if(map.emited[unit.name]) {
        delete map.emited[unit.name];
        b = true;
    }else if(map.finished[unit.name]) {
        delete map.finished[unit.name];
        b = true;
    }
    if(b) {
        console.warn("已经注册过名为"+unit.name+"的过程");
    }
    // if(map.awaiting[unit.name] || map.emited[unit.name] || map.finished[unit.name]) {
    //     // throw Error("已经注册过名为"+unit.name+"的过程");
    //     console.warn("已经注册过名为"+unit.name+"的过程");
    // }
    map.awaiting[unit.name] = unit;
}
process.clear = function() {
    map.finished = {};
    map.emited = {};
    map.awaiting = {};
}

function unloadProcess(name) {
    if(map.awaiting[name]) delete map.awaiting[name];
    else if(map.emited[name]) delete map.emited[name];
    else if(map.finished[name]) delete map.finished[name];
}


function checkProcess() {
    var awaiting = {};
    for(var key in map.awaiting) {
        var unit = map.awaiting[key];
        var b = true;
        for(var i = unit._premise_begin_index; i < unit.premise.length; i++) {
            if(!map.finished[unit.premise[i]]) {
                unit._premise_begin_index = i;
                b = false;
                break;
            }
        }
        if(b) {
            map.emited[unit.name] = unit;
            createTimeout(unit);
        }else {
            awaiting[unit.name] = unit;
        }
    }
    map.awaiting = awaiting;
}

function createTimeout(unit) {
    setTimeout(function() { // 为了不阻塞当前的循环检测
        unit.fn({
            current_process: unit,
            unload: unloadProcess
        });
        delete map.emited[unit.name];
        if(unit.name[0] != "_") map.finished[unit.name] = unit;
    }, 0);
}

setInterval(function() {
    checkProcess();
}, 0);

export default process;
 
 

